package com.sunday.common.spring.study;

import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.context.SmartLifecycle;
import org.springframework.stereotype.Component;

/**
 *
 * spring加载顺序测试
 *
 * 启发类
 * com.xxl.job.core.executor.impl.XxlJobSpringExecutor
 * com.xxl.job.admin.core.conf.XxlJobAdminConfig
 *
 * <p>
 * InitializingBean
 * <p>
 * 1. InitializingBean接口为bean提供了初始化方法的方式，它只包括afterPropertiesSet方法，凡是继承该接口的类，在初始化bean的时候都会执行该方法。
 * 2. spring初始化bean的时候，如果bean实现了InitializingBean接口，会自动调用afterPropertiesSet方法。
 * 3. 在Spring初始化bean的时候，如果该bean实现了InitializingBean接口，并且同时在配置文件中指定了init-method，@Bean(initMethod = "init")系统则是先调用afterPropertieSet()方法，然后再调用init-method中指定的方法。
 * 4. Constructor > @PostConstruct > InitializingBean > init-method
 * <p>
 * DisposableBean
 * <p>
 * 1. 在Bean生命周期结束前调用destory()方法做一些收尾工作，亦可以使用destory-method。
 * 2. 前者与Spring耦合高，使用类型强转.方法名()，效率高。 后者耦合低，使用反射，效率相对低
 * <p>
 * SmartLifecycle  https://www.jb51.net/article/223815.htm
 * <p>
 * 在使用Spring开发时，我们都知道，所有bean都交给Spring容器来统一管理，其中包括每一个bean的加载和初始化。
 * 有时候我们需要在Spring加载和初始化所有bean后，接着执行一些任务或者启动需要的异步服务，这样我们可以使用 SmartLifecycle 来做到。
 * <p>
 * SmartInitializingSingleton https://blog.csdn.net/fox9916/article/details/129042652
 * <p>
 * 1、SmartInitializingSingleton主要用于在Spring容器启动完成时进行扩展操作，即afterSingletonsInstantiated()；
 * 2、实现SmartInitializingSingleton接口的bean的作用域必须是单例，afterSingletonsInstantiated()才会触发；
 * 3、afterSingletonsInstantiated()触发执行时，非懒加载的单例bean已经完成实现化、属性注入以及相关的初始化操作；
 */
@Slf4j
@Component
public class StartBean implements InitializingBean, DisposableBean, SmartInitializingSingleton, SmartLifecycle {

    public StartBean() {
        log.info("我是InitializingBeanTest构造方法执行...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("我是afterPropertiesSet方法执行...");
    }

    @Override
    public void afterSingletonsInstantiated() {
        log.info("我是afterSingletonsInstantiated方法执行...");
    }

    @PostConstruct
    public void postConstruct() {
        log.info("我是postConstruct方法执行...");
    }

    public void init() {
        log.info("我是init方法执行...");
    }

//    @Bean(initMethod = "init")
//    public StartBean test() {
//        return new StartBean();
//    }

    @Override
    public void destroy() throws Exception {
        log.info("我是destroy方法执行...");
    }


    @Override
    public void start() {
        log.info("我是start方法执行...");
    }

    @Override
    public void stop() {
        log.info("我是stop方法执行...");
    }

    @Override
    public boolean isRunning() {
        return true;
    }
}
